<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <input type="button" value="Click" id="btn1"/>
        <script type="text/javascript">
            var btn = document.getElementById("btn1");
            function f1() {
                alert('f1');
            }
            function f2() {
                alert(this); //this指向触发此事件的元素
                alert('f2');
            }
            function fa(a) {
                alert(a);
            }
            //.onclick方式绑定绑定函数：若同时绑定多个函数，只会执行最后一个函数
            //          btn.onclick = f1;
            //                     btn.onclick = f2;
            //          btn.onclick = fa('fa');  //可以传递参数

            //IE的.attachEvent方式: 若同时绑定多个函数，多个函数均会执行，后绑定的先执行
            //object.attachEvent(event,function);
            //                    btn.attachEvent("onclick",f1);
            //                    btn.attachEvent("onclick",f2);
            //如果是带参数的函数，会出现问题,  会先执行函数
            //btn.attachEvent("onclick",fa('fa'));
            //可通过此种方式传递
            //btn.attachEvent("onclick",function(){fa('fa')});
            //Firefox W3C的addEventListener方式：若同时绑定多个函数，多个函数均会执行，先绑定的先执行
            //element.addEventListener(type,listener,useCapture);  第三个参数涉及到多层事件嵌套
            //    * true 的触发顺序总是在 false 之前；
            //    * 如果多个均为 true，则外层的触发先于内层；
            //    * 如果多个均为 false，则内层的触发先于外层。
            //btn.addEventListener("click",f1,true);
            btn.addEventListener("click",f2,true);

            //浏览器兼容写法
            //1
            function addEvent(elm, evType, fn, useCapture) {
                if (elm.addEventListener) {
                    elm.addEventListener(evType, fn, useCapture);//DOM2.0
                    return true;
                }
                else if (elm.attachEvent) {
                    var r = elm.attachEvent('on' + evType, fn);//IE5+
                    return r;
                }
                else {
                    elm['on' + evType] = fn;//DOM 0
                }
            }
            //addEvent(btn, 'click', f1, true);

            //2.
            var addEvent=(function(){
                if(document.addEventListener){
                    return function(el,type,fn){
                        if(el.length){
                            for(var i=0;i<el.length;i++){
                                addEvent(el[i],type,fn);
                            }
                        }else{
                            el.addEventListener(type,fn,false);
                        }
                    };
                }else{
                    return function(el,type,fn){
                        if(el.length){
                            for(var i=0;i<el.length;i++){
                                addEvent(el[i],type,fn);
                            }
                        }else{
                            el.attachEvent('on'+type,function(){
                                return fn.call(el,window.event);
                            });
                        }
                    };
                }
            })();
            //addEvent(btn, 'click', f2);

            //3.
            function addEvent(element, type, handler) {
                //为每一个事件处理函数分派一个唯一的ID
                if (!handler.$$guid) handler.$$guid = addEvent.guid++;
                //为元素的事件类型创建一个哈希表 events
                if (!element.events) element.events = {};
                //为每一个"元素/事件"对创建一个事件处理程序的哈希表，每一个元素可能有多个处理函数
                var handlers = element.events[type];
                if (!handlers) {
                    handlers = element.events[type] = {};
                    //存储已经存在的事件处理函数(如果有)
                    if (element["on" + type]) {
                        handlers[0] = element["on" + type];
                    }
                }
                //将事件处理函数存入哈希表
                handlers[handler.$$guid] = handler;
                //指派一个全局的事件处理函数来做所有的工作
                element["on" + type] = handleEvent;
            };
            //用来创建唯一的ID的计数器
            addEvent.guid = 1;
            function removeEvent(element, type, handler) {
                //从哈希表中删除事件处理函数
                if (element.events && element.events[type]) {
                    delete element.events[type][handler.$$guid];  //delete运算符删除对象，删除对象本身，删除的对象变为undefined
                }
            };
            function handleEvent(event) {
                //this指向元素
                var returnValue = true;
                //抓获事件对象(IE使用全局事件对象)
                event = event || fixEvent(window.event);
                //取得事件处理函数的哈希表的引用（可能有多个处理函数）
                var handlers = this.events[event.type];
                //执行每一个处理函数
                for (var i in handlers) {
                    this.$$handleEvent = handlers[i];
                    //执行
                    if (this.$$handleEvent(event) === false) {
                        returnValue = false;
                    }
                }
                return returnValue;
            };
            //为IE的事件对象添加一些“缺失的”函数【详细解释信息见http://www.w3school.com.cn/htmldom/dom_obj_event.asp】
            function fixEvent(event) {
                //添加标准的W3C方法
                event.preventDefault = fixEvent.preventDefault;
                event.stopPropagation = fixEvent.stopPropagation;
                return event;
            };
            fixEvent.preventDefault = function() {
                this.returnValue = false;
            };
            fixEvent.stopPropagation = function() {
                this.cancelBubble = true;
            };
        </script>
    </body>
</html>
